一步步带你编译哔哩哔哩ijkPlayer
今日科技快讯
2月24日,中兴手机宣布将在明天也就是2月25日,正式发布旗下首款5G旗舰手机,而此次他们是联合中国联通一起。 据悉,中兴将发布的5G手机是天机Axon 10 Pro,预计2019年上半年即可率先在欧洲和中国市场上市。目前,中国联通已经完成了5G网络第三个测试阶段,距离正式商用又近了一步。
作者简介
大家周一好,新的一周继续努力吧!
本篇来自 Overried 的投稿文章。文章分享了Android中 JNI开发中如何编译使用bilibili/ijkPlayer,希望对大家有所帮助。
Overried 的博客地址:
https://www.jianshu.com/u/75711cf32043
视频库播放库哪家强
视频播放库 | bilibili/ijkplayer | google/ExoPlayer | VLC-Android |
支持ffmpeg拓展 | 支持 | 不支持 | 嵌入ffmpeg 的 libavcodec库 |
可拓展性 | 高 | 无 | 低,需要二次开发 |
体积大小 | 5M-45M | 无体积 | 13M |
播放的视频格式 | 只要ffmpeg支持都支持 | 支持手机支持播放的 | 大多数易见视频 |
start | 2.1W | 1.2W | GitLab 296个 |
issue | 2116 Open/2318 Close | 201 Open/4389 Close | 169 Open/544 Close |
是否持续维护 | 维护中 | 维护中 | 维护中 |
分析 ijkPlayer 构建流程
找到ijkplayer 的 github 主页
看了一下这目录结构,en .... ,果然没看懂,是不是越是庞大的项目,越是喜欢整这些让人摸不着头脑的目录结构要存放代码文件。(其实官方是为了模块化代码结构),那这个要从哪里入手。
先看简介 readme.md ,整理出下面一个流程图
构建 ijkplayer
按照 readme.md 的流程来
搭建 linux 环境
傻瓜式安装
下载Ubuntu
下载VMWare
搭建 JDK(linux) + Android SDK(linux + NDK(linux)
JDK
sudo apt-get install openjdk-8-kdk
//配置环境变量:
sudo gedit /etc/profile
export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
Android SDK(linux)
1)手动下载
2)进入目录 /androidSDK/sdk-tools-linux/tools/bin ,
执行 ./sdkmanager --list 命令看下有哪些目录可以下载:
接着拉必要的目录,执行以下命令
./sdkmanager "add-ons;addon-google_apis-google-24" "add-ons;addon-google_apis-google-24" "platform-tools" "platforms;android-28" "tools"
3)配置环境变量
sudo gedit /etc/profile
export ANDROID_SDK=/home/jiong/androidSDK/android-sdk-linux
export PATH=${PATH}:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools
下载 android-ndk-r14b-linux-x86_64.zip
sudo gedit /etc/profile
export ANDROID_NDK=/home/jiong/androidNDK/android-ndk-r14b
export PATH=$ANDROID_NDK:$PATH
手动下载 ijkpalyer ,并放到 ubuntu的任意一个目录下。
拉取 ijkpalyer JNI 和 ffmpeg 代码
cd ijkplayer-android
./init-android.sh
拉取 openssl 代码
./init-android-openssl.sh
编译openssl代码
cd android/contrib
./compile-openssl.sh clean
./compile-openssl.sh all7、选择配置ffmpeg信息
选择配置ffmpeg信息
cd ../../
cd config
rm module.sh
ln -s module-lite.sh module.sh
//如果需要支持更多的视频格式用下面的配置
// ln -s module-default.sh module.sh
编译 ffmpeg 代码
cd ../
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
编译 ijkplayer jni 代码(依赖ffmpeg库)
cd ..
./compile-ijk.sh all
迁移 ijkplayer 到 android studio
拷贝 编译好的这个 /ijkplayer-android/android 目录,用android studio 导入这个工程(源码4.1G 有点大 )
看下主要库的大小-- 一共4.8M左右
跑起来:
但是结果发现 .avi .dv .asf的视频都不支持
修改 ffmpeg 的参数
//这里的配置换成下面的配置参数,这里是 linux 软引用表示 module.sh 文件名,代表了module-default.sh 文件
//ln -s module-lite.sh module.sh
ln -s module-default.sh module.sh
编译ffmpeg脚本do-compile-ffmpeg.sh 文件里面有这么一句代码:
export COMMON_FF_CFG_FLAGS=.$FF_BUILD_ROOT/../../config/module.sh
我们来看一下两者的脚本有哪些不同:左边脚本支持的编码全开(默认),右边脚本,全部先关闭,再开几个支持的。
重新编译出 ffmpeg
使用全部开启的编译脚本,编译出 so 。46M ,果然够大
重新跑一下, avi 、asf 、dv都能播放了
如果每次都要在 linux 编译出 so ,再移到 android studio 上跑非常麻烦,如何把ijkpalyer 的jni 源码放到 android studio一键编译。看下面:
在linux 下观察 jni 文件夹有哪些文件,其中有两个是链接文件(右下角有个箭头),并且三个文件夹都是空文件,没有放置源码在里面。
android-ndk-prof 源码在以下文件夹(右键属性,可以看到真实文件的路径)
/ijkplayer-android/android-ndk-profiler-dummy/jni
ffmpeg 的 so 库文件,以及include 文件夹在以下文件夹(看complie-ffmpeg.sh 的脚本语言打包的输出路径)
/ijkplayer-android/android/contrib/build/ffmpeg-armv7a/output
ijkmedia源码在以下文件夹(右键属性,可以看到真实文件的路径)
/ijkplayer-android/ijkmedia
全部拷贝过去,ffmpeg 拷贝 so库以及头文件 过去即可,毕竟ffmpeg 一般不需要二次开发,有bug 等更新就可以,不然每次编译 十几分钟,太长。android-ndk-profiler-dummy 和ijkmedia模块就把源码拷贝过来。 结果位置见下图:
接下来需要修改 /jni/Android.mk,不然编译不过去:
旧代码
LOCAL_PATH := $(call my-dir)
MY_APP_JNI_ROOT := $(realpath $(LOCAL_PATH))
MY_APP_PRJ_ROOT := $(realpath $(MY_APP_JNI_ROOT)/..)
MY_APP_ANDROID_ROOT := $(realpath $(MY_APP_PRJ_ROOT)/../../../..)
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-armv7a/output)
MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
endif
ifeq ($(TARGET_ARCH_ABI),armeabi)
MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-armv5/output)
MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
endif
ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-arm64/output)
MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
endif
ifeq ($(TARGET_ARCH_ABI),x86)
MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-x86/output)
MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
endif
ifeq ($(TARGET_ARCH_ABI),x86_64)
MY_APP_FFMPEG_OUTPUT_PATH := $(realpath $(MY_APP_ANDROID_ROOT)/contrib/build/ffmpeg-x86_64/output)
MY_APP_FFMPEG_INCLUDE_PATH := $(realpath $(MY_APP_FFMPEG_OUTPUT_PATH)/include)
endif
include $(call all-subdir-makefiles)
由于 jni 需要使用相对路径 ,去掉$(realpath),这里只保留armeabi-v7a改成:
LOCAL_PATH := $(call my-dir)
MY_APP_ANDROID_ROOT := $(LOCAL_PATH)
MY_APP_FFMPEG_OUTPUT_PATH := $(MY_APP_ANDROID_ROOT)/ffmpeg/lib
MY_APP_FFMPEG_INCLUDE_PATH := $(MY_APP_ANDROID_ROOT)/ffmpeg/include
include $(call all-subdir-makefiles) //找到所有目录下第一层子目录的 android.mk 进行编译
ijkmedia 模块下面的第一层文件夹 凡是有 Android.mk 的,并且里面使用 $(realpath $(LOCAL_PATH)) 的,都要把 $(realpath)去掉。
好了在 android studio 编译起来:
跑起来,大功告成: